package com.zhuojy.equity.mall.admin.web.security.component;

import cn.hutool.core.util.URLUtil;
import com.zhuojy.equity.mall.admin.dal.dataobject.TResourceDO;
import com.zhuojy.equity.mall.admin.manager.ResourceManager;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

import javax.annotation.PostConstruct;
import java.util.*;

/**
 * 动态权限数据源，用于获取动态权限规则
 */
@Component
@RequiredArgsConstructor
public class DynamicSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

	private static Map<String, ConfigAttribute> configAttributeMap = new HashMap<>();

	private final ResourceManager resourceManager;

	/**
	 * 加载资源ANT通配符和资源对应MAP
	 */
	@PostConstruct
	public void loadDataSource() {
		List<TResourceDO> resourceList = resourceManager.queryAllResource();
		for (TResourceDO resourceDO : resourceList) {
			configAttributeMap.put(resourceDO.getUrl(),
					new SecurityConfig(resourceDO.getId() + ":" + resourceDO.getName()));
		}
	}

	public void clearDataSource() {
		configAttributeMap.clear();
		configAttributeMap = null;
	}

	@Override
	public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
		if (configAttributeMap == null) {
			this.loadDataSource();
		}
		List<ConfigAttribute> configAttributes = new ArrayList<>();
		//获取当前访问的路径
		String url = ((FilterInvocation) o).getRequestUrl();
		String path = URLUtil.getPath(url);
		PathMatcher pathMatcher = new AntPathMatcher();
		//获取访问该路径所需资源
		for (String pattern : configAttributeMap.keySet()) {
			if (pathMatcher.match(pattern, path)) {
				configAttributes.add(configAttributeMap.get(pattern));
			}
		}
		// 未设置操作请求权限，返回空集合
		return configAttributes;
	}

	@Override
	public Collection<ConfigAttribute> getAllConfigAttributes() {
		return null;
	}

	@Override
	public boolean supports(Class<?> aClass) {
		return true;
	}

}
